// 版权所有2009 Go作者。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// 包reflectlite实现了reflect的轻量级版本，不使用
// 除“运行时”和“不安全”之外的任何包。
package reflectlite

import (
	"internal/unsafeheader"
	"unsafe"
)

// 类型是Go类型的表示形式。
// 
// 并非所有方法都适用于所有类型。每种方法的文档中都注明了限制条件，如有。
// 在调用特定于种类的方法之前，使用种类方法找出类型的种类。调用方法
// 不适合该类型会导致运行时死机。
// 
// 类型值是可比较的，例如使用==运算符，
// 因此它们可以用作映射键。
// 如果两个类型值表示相同的类型，则它们相等。
type Type interface {
	// 适用于所有类型的方法。

	// Name返回定义类型的包中的类型名称。
	// 对于其他（未定义）类型，它返回空字符串。
	Name() string

	// PkgPath返回定义类型的包路径，即唯一标识包的导入路径
	// 如“encoding/base64”。
	// 如果类型是预先声明的（字符串，错误）或未定义（*T，struct{}，
	// /[]int，或A是未定义类型的别名，则包路径
	// 将是空字符串。
	PkgPath() string

	// Size返回存储给定类型的值所需的字节数；它类似于unsafe.Sizeof。
	Size() uintptr

	// Kind返回此类型的特定种类。
	Kind() Kind

	// Implements报告该类型是否实现接口类型u。
	Implements(u Type) bool

	// AssignableTo报告类型的值是否可分配给类型u。
	AssignableTo(u Type) bool

	// 可比报告此类型的值是否可比。
	Comparable() bool

	// String返回该类型的字符串表示形式。
	// 字符串表示可以使用缩短的包名
	// （例如，base64而不是“encoding/base64”），并且不能保证
	// 在类型中是唯一的。要测试类型标识，请直接比较类型。
	String() string

	// Elem返回类型的元素类型。
	// 如果类型的种类不是Ptr，它会恐慌。
	Elem() Type

	common() *rtype
	uncommon() *uncommonType
}

/*
 * These data structures are known to the compiler (../../cmd/internal/reflectdata/reflect.go).
 * A few are known to ../runtime/type.go to convey to debuggers.
 * They are also known to ../runtime/type.go.
 */

// 一个种类代表一个种类所代表的特定种类的类型。
// 零类型不是有效类型。
type Kind uint

const (
	Invalid Kind = iota
	Bool
	Int
	Int8
	Int16
	Int32
	Int64
	Uint
	Uint8
	Uint16
	Uint32
	Uint64
	Uintptr
	Float32
	Float64
	Complex64
	Complex128
	Array
	Chan
	Func
	Interface
	Map
	Ptr
	Slice
	String
	Struct
	UnsafePointer
)

// tflag被一个rtype用来表示什么是额外的类型信息
// 直接在rtype值后面的内存中可用。
// 
// tflag值必须与中的副本保持同步：
// cmd/compile/internal/reflectdata/reflect.go 
// cmd link/internal/ld/decodesym.go 
// runtime/type.go 
type tflag uint8

const (
	// tflag表示有一个指针，*uncomontype，
	// 仅超出外部类型结构。
	// 
	// 例如，如果t.Kind（）==Struct和t.tflag&tflag！=0，
	// t有uncommonType数据，可以访问为：
	// 
	// type tuncomon struct{
	// /structType 
	// u uncommonType 
	// 
	// /u:=（*tuncomon）（不安全的指针（t））.u 
	tflagUncommon tflag = 1 << 0

	// tflagExtraStar表示str字段中的名称有一个
	// 额外的“*”前缀。这是因为对于
	// 程序中的大多数类型T，类型*T也存在，重用str数据
	// 可以节省二进制大小。
	tflagExtraStar tflag = 1 << 1

	// tflagNamed表示该类型具有名称。
	tflagNamed tflag = 1 << 2

	// tflagRegularMemory意味着equal和hash函数可以将
	// 此类型视为t.size字节的单个区域。
	tflagRegularMemory tflag = 1 << 3
)

// rtype是大多数值的常见实现。
// 它嵌入到其他结构类型中。
// 
// rtype必须与../runtime/type保持同步。go:
type rtype struct {
	size       uintptr
	ptrdata    uintptr // 类型中可以包含指针的字节数
	hash       uint32  // 类型的哈希；避免哈希表中的计算
	tflag      tflag   // 额外类型信息标志
	align      uint8   // 将变量与此类型对齐
	fieldAlign uint8   // 将结构字段与此类型对齐
	kind       uint8   // 枚举C 
	// 用于比较此类型对象的函数
	// （ptr到对象A，ptr到对象B）->=？
	equal     func(unsafe.Pointer, unsafe.Pointer) bool
	gcdata    *byte   // 垃圾收集数据
	str       nameOff // 字符串形式
	ptrToThis typeOff // 指向此类型的指针类型，可以是零
}

// 非接口类型上的方法
type method struct {
	name nameOff // 方法名称
	mtyp typeOff // 方法类型（不带接收器）
	ifn  textOff // 用于接口调用的fn（单字接收器）
	tfn  textOff // fn用于常规方法调用
}

// uncoMonType仅用于已定义的类型或具有方法的类型
// （如果T是已定义的类型，则T和*T的uncoMonType具有方法）。
// 使用指向此结构的指针可减少描述无方法的未定义类型所需的总大小。
type uncommonType struct {
	pkgPath nameOff // 导入路径；内置类型（如int）为空，字符串
	mcount  uint16  // 方法数
	xcount  uint16  // 导出方法数
	moff    uint32  // 从此uncommontype到[mcount]方法的偏移量
	_       uint32  // 未使用的
}

// chanDir表示通道类型的方向。
type chanDir int

const (
	recvDir chanDir             = 1 << iota // <-chan 
	sendDir                                 // chan<-
	bothDir = recvDir | sendDir             // chan 
)

// arrayType表示固定数组类型。
type arrayType struct {
	rtype
	elem  *rtype // 数组元素类型
	slice *rtype // 切片类型
	len   uintptr
}

// chanType表示通道类型。
type chanType struct {
	rtype
	elem *rtype  // 通道元素类型
	dir  uintptr // 通道方向（chanDir）
}

// funcType表示函数类型。
// 
// A*rtype用于每个in和out参数，存储在一个数组中，
// 直接跟随funcType（可能还有它的uncommonType）。所以
// 一个方法、一个输入、一个输出的函数类型是：
// 
// struct{
// /funcType 
// /unomonType 
// /[2]*rtype/[0]在[1]在外
type funcType struct {
	rtype
	inCount  uint16
}

// i方法表示接口类型上的方法
type imethod struct {
	name nameOff // 方法名称
	typ  typeOff // /.（*FuncType）位于
}

// interfaceType表示接口类型。
type interfaceType struct {
	rtype
	pkgPath name      // 导入路径
	methods []imethod // 按哈希排序
}

// mapType表示映射类型。
type mapType struct {
	rtype
	key    *rtype // 映射键类型
	elem   *rtype // 映射元素（值）类型
	bucket *rtype // 内部桶结构
	// 散列键函数（ptr到键，种子）->hash 
	hasher     func(unsafe.Pointer, uintptr) uintptr
	keysize    uint8  // 键槽大小
	valuesize  uint8  // 值槽大小
	bucketsize uint16 // bucket大小
	flags      uint32
}

// ptrType表示指针类型。
type ptrType struct {
	rtype
	elem *rtype // 指针元素（指向）类型
}

// 切片类型表示切片类型。
type sliceType struct {
	rtype
	elem *rtype // 切片元素类型
}

// 结构字段
type structField struct {
	name        name    // 名称始终为非空
	typ         *rtype  // 字段类型
	offsetEmbed uintptr // 字段的字节偏移量<<1；已嵌入
}

func (f *structField) offset() uintptr {
	return f.offsetEmbed >> 1
}

func (f *structField) embedded() bool {
	return f.offsetEmbed&1 != 0
}

// structType表示结构类型。
type structType struct {
	rtype
	pkgPath name
	fields  []structField // 按偏移量排序
}

// 名称是一个带有可选额外数据的编码类型名称。
// 
// 第一个字节是一个包含以下内容的位字段：
// 
// 1<<0导出名称
// 1<<1标记数据跟在名称后面
// 1<<2 pkgPath nameOff跟在名称后面，标记
// 
// 接下来的两个字节是数据长度：
// 
// l:=uint16（数据[1]）<uint16（数据[2]）
// 
// 字节[3:3+l]为字符串数据。
// 
// 如果后面是标记数据，则字节3+l和3+l+1是标记长度，
// 后面是数据。
// 
// 如果导入路径跟随，则在
// 末尾的4个字节将形成一个名称。导入路径仅为具体的
// 方法设置，这些方法定义在与其类型不同的包中。
// 
// 如果名称以“*”开头，则导出的位表示
// 是否导出指向的类型。
type name struct {
	bytes *byte
}

func (n name) data(off int, whySafe string) *byte {
	return (*byte)(add(unsafe.Pointer(n.bytes), uintptr(off), whySafe))
}

func (n name) isExported() bool {
	return (*n.bytes)&(1<<0) != 0
}

func (n name) hasTag() bool {
	return (*n.bytes)&(1<<1) != 0
}

// readVarint将varint解析为encoding/binary编码的变量。
// 返回编码字节数和编码值。
func (n name) readVarint(off int) (int, int) {
	v := 0
	for i := 0; ; i++ {
		x := *n.data(off+i, "read varint")
		v += int(x&0x7f) << (7 * i)
		if x&0x80 == 0 {
			return i + 1, v
		}
	}
}

func (n name) name() (s string) {
	if n.bytes == nil {
		return
	}
	i, l := n.readVarint(1)
	hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
	hdr.Data = unsafe.Pointer(n.data(1+i, "non-empty string"))
	hdr.Len = l
	return
}

func (n name) tag() (s string) {
	if !n.hasTag() {
		return ""
	}
	i, l := n.readVarint(1)
	i2, l2 := n.readVarint(1 + i + l)
	hdr := (*unsafeheader.String)(unsafe.Pointer(&s))
	hdr.Data = unsafe.Pointer(n.data(1+i+l+i2, "non-empty string"))
	hdr.Len = l2
	return
}

func (n name) pkgPath() string {
	if n.bytes == nil || *n.data(0, "name flag field")&(1<<2) == 0 {
		return ""
	}
	i, l := n.readVarint(1)
	off := 1 + i + l
	if n.hasTag() {
		i2, l2 := n.readVarint(off)
		off += i2 + l2
	}
	var nameOff int32
	// 注意，这个字段在内存中可能没有对齐，因此我们不能在这里使用直接的int32赋值。
	copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.data(off, "name offset field")))[:])
	pkgPathName := name{(*byte)(resolveTypeOff(unsafe.Pointer(n.bytes), nameOff))}
	return pkgPathName.name()
}

/*
 * The compiler knows the exact layout of all the data structures above.
 * The compiler does not know about the data structures and methods below.
 */

const (
	kindDirectIface = 1 << 5
	kindGCProg      = 1 << 6 // Type.gc指向gc程序
	kindMask        = (1 << 5) - 1
)

// String返回k的名称。
func (k Kind) String() string {
	if int(k) < len(kindNames) {
		return kindNames[k]
	}
	return kindNames[0]
}

var kindNames = []string{
	Invalid:       "invalid",
	Bool:          "bool",
	Int:           "int",
	Int8:          "int8",
	Int16:         "int16",
	Int32:         "int32",
	Int64:         "int64",
	Uint:          "uint",
	Uint8:         "uint8",
	Uint16:        "uint16",
	Uint32:        "uint32",
	Uint64:        "uint64",
	Uintptr:       "uintptr",
	Float32:       "float32",
	Float64:       "float64",
	Complex64:     "complex64",
	Complex128:    "complex128",
	Array:         "array",
	Chan:          "chan",
	Func:          "func",
	Interface:     "interface",
	Map:           "map",
	Ptr:           "ptr",
	Slice:         "slice",
	String:        "string",
	Struct:        "struct",
	UnsafePointer: "unsafe.Pointer",
}

func (t *uncommonType) methods() []method {
	if t.mcount == 0 {
		return nil
	}
	return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.mcount > 0"))[:t.mcount:t.mcount]
}

func (t *uncommonType) exportedMethods() []method {
	if t.xcount == 0 {
		return nil
	}
	return (*[1 << 16]method)(add(unsafe.Pointer(t), uintptr(t.moff), "t.xcount > 0"))[:t.xcount:t.xcount]
}

// resolveNameOff解析与基指针的名称偏移量。
// （*rtype）.nameOff方法是此函数的方便包装器。
// 在运行时包中实现。
func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer

// resolveTypeOff解析基类型的*rtype偏移量。
// （*rtype）.typeOff方法是此函数的方便包装器。
// 在运行时包中实现。
func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer

type nameOff int32 // 到名称的偏移量
type typeOff int32 // 到*rtype 
type textOff int32 // 到文本段顶部的偏移量

func (t *rtype) nameOff(off nameOff) name {
	return name{(*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
}

func (t *rtype) typeOff(off typeOff) *rtype {
	return (*rtype)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
}

func (t *rtype) uncommon() *uncommonType {
	if t.tflag&tflagUncommon == 0 {
		return nil
	}
	switch t.Kind() {
	case Struct:
		return &(*structTypeUncommon)(unsafe.Pointer(t)).u
	case Ptr:
		type u struct {
			ptrType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	case Func:
		type u struct {
			funcType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	case Slice:
		type u struct {
			sliceType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	case Array:
		type u struct {
			arrayType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	case Chan:
		type u struct {
			chanType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	case Map:
		type u struct {
			mapType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	case Interface:
		type u struct {
			interfaceType
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	default:
		type u struct {
			rtype
			u uncommonType
		}
		return &(*u)(unsafe.Pointer(t)).u
	}
}

func (t *rtype) String() string {
	s := t.nameOff(t.str).name()
	if t.tflag&tflagExtraStar != 0 {
		return s[1:]
	}
	return s
}

func (t *rtype) Size() uintptr { return t.size }

func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) }

func (t *rtype) pointers() bool { return t.ptrdata != 0 }

func (t *rtype) common() *rtype { return t }

func (t *rtype) exportedMethods() []method {
	ut := t.uncommon()
	if ut == nil {
		return nil
	}
	return ut.exportedMethods()
}

func (t *rtype) NumMethod() int {
	if t.Kind() == Interface {
		tt := (*interfaceType)(unsafe.Pointer(t))
		return tt.NumMethod()
	}
	return len(t.exportedMethods())
}

func (t *rtype) PkgPath() string {
	if t.tflag&tflagNamed == 0 {
		return ""
	}
	ut := t.uncommon()
	if ut == nil {
		return ""
	}
	return t.nameOff(ut.pkgPath).name()
}

func (t *rtype) hasName() bool {
	return t.tflag&tflagNamed != 0
}

func (t *rtype) Name() string {
	if !t.hasName() {
		return ""
	}
	s := t.String()
	i := len(s) - 1
	for i >= 0 && s[i] != '.' {
		i--
	}
	return s[i+1:]
}

func (t *rtype) chanDir() chanDir {
	if t.Kind() != Chan {
		panic("reflect: chanDir of non-chan type")
	}
	tt := (*chanType)(unsafe.Pointer(t))
	return chanDir(tt.dir)
}

func (t *rtype) Elem() Type {
	switch t.Kind() {
	case Array:
		tt := (*arrayType)(unsafe.Pointer(t))
		return toType(tt.elem)
	case Chan:
		tt := (*chanType)(unsafe.Pointer(t))
		return toType(tt.elem)
	case Map:
		tt := (*mapType)(unsafe.Pointer(t))
		return toType(tt.elem)
	case Ptr:
		tt := (*ptrType)(unsafe.Pointer(t))
		return toType(tt.elem)
	case Slice:
		tt := (*sliceType)(unsafe.Pointer(t))
		return toType(tt.elem)
	}
	panic("reflect: Elem of invalid type")
}

func (t *rtype) In(i int) Type {
	if t.Kind() != Func {
		panic("reflect: In of non-func type")
	}
	tt := (*funcType)(unsafe.Pointer(t))
	return toType(tt.in()[i])
}

func (t *rtype) Key() Type {
	if t.Kind() != Map {
		panic("reflect: Key of non-map type")
	}
	tt := (*mapType)(unsafe.Pointer(t))
	return toType(tt.key)
}

func (t *rtype) Len() int {
	if t.Kind() != Array {
		panic("reflect: Len of non-array type")
	}
	tt := (*arrayType)(unsafe.Pointer(t))
	return int(tt.len)
}

func (t *rtype) NumField() int {
	if t.Kind() != Struct {
		panic("reflect: NumField of non-struct type")
	}
	tt := (*structType)(unsafe.Pointer(t))
	return len(tt.fields)
}

func (t *rtype) NumIn() int {
	if t.Kind() != Func {
		panic("reflect: NumIn of non-func type")
	}
	tt := (*funcType)(unsafe.Pointer(t))
	return int(tt.inCount)
}

func (t *rtype) NumOut() int {
	if t.Kind() != Func {
		panic("reflect: NumOut of non-func type")
	}
	tt := (*funcType)(unsafe.Pointer(t))
	return len(tt.out())
}

func (t *rtype) Out(i int) Type {
	if t.Kind() != Func {
		panic("reflect: Out of non-func type")
	}
	tt := (*funcType)(unsafe.Pointer(t))
	return toType(tt.out()[i])
}

func (t *funcType) in() []*rtype {
	uadd := unsafe.Sizeof(*t)
	if t.tflag&tflagUncommon != 0 {
		uadd += unsafe.Sizeof(uncommonType{})
	}
	if t.inCount == 0 {
		return nil
	}
	return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.inCount:t.inCount]
}

func (t *funcType) out() []*rtype {
	uadd := unsafe.Sizeof(*t)
	if t.tflag&tflagUncommon != 0 {
		uadd += unsafe.Sizeof(uncommonType{})
	}
	outCount := t.outCount & (1<<15 - 1)
	if outCount == 0 {
		return nil
	}
	return (*[1 << 20]*rtype)(add(unsafe.Pointer(t), uadd, "outCount > 0"))[t.inCount : t.inCount+outCount : t.inCount+outCount]
}

// add返回p+x。
// 
// 忽略whySafe字符串，因此函数仍然像p+x一样高效地内联
// 但所有调用站点都应该使用该字符串来记录为什么添加是安全的，也就是说，为什么加法
// 不会导致x前进到p的分配
// 的最后，因此不能正确地指向内存中的下一个块。
func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
	return unsafe.Pointer(uintptr(p) + x)
}

// NumMethod返回类型的方法集中的接口方法数。
func (t *interfaceType) NumMethod() int { return len(t.methods) }

// TypeOf返回表示i的动态类型的反射类型。
// 如果i是nil接口值，则TypeOf返回nil。
func TypeOf(i interface{}) Type {
	eface := *(*emptyInterface)(unsafe.Pointer(&i))
	return toType(eface.typ)
}

func (t *rtype) Implements(u Type) bool {
	if u == nil {
		panic("reflect: nil type passed to Type.Implements")
	}
	if u.Kind() != Interface {
		panic("reflect: non-interface type passed to Type.Implements")
	}
	return implements(u.(*rtype), t)
}

func (t *rtype) AssignableTo(u Type) bool {
	if u == nil {
		panic("reflect: nil type passed to Type.AssignableTo")
	}
	uu := u.(*rtype)
	return directlyAssignable(uu, t) || implements(uu, t)
}

func (t *rtype) Comparable() bool {
	return t.equal != nil
}

// implements报告类型V是否实现了接口类型T。
func implements(T, V *rtype) bool {
	if T.Kind() != Interface {
		return false
	}
	t := (*interfaceType)(unsafe.Pointer(T))
	if len(t.methods) == 0 {
		return true
	}

	// 相同的算法适用于这两种情况，但接口类型和具体类型的
	// 方法表不同，因此代码重复。
	// 在这两种情况下，算法都是对两个
	// 同时列出T方法和V方法的线性扫描。
	// 由于方法表以唯一的排序顺序存储
	// （按字母顺序，没有重复的方法名称），因此通过V的方法扫描
	// 必须与T的每个
	// 方法匹配，否则V不实现T。
	// 这使我们可以在整个线性时间内运行扫描，而不是在简单搜索所需的二次时间内运行扫描。
	// 另请参见../runtime/iface.go。
	if V.Kind() == Interface {
		v := (*interfaceType)(unsafe.Pointer(V))
		i := 0
		for j := 0; j < len(v.methods); j++ {
			tm := &t.methods[i]
			tmName := t.nameOff(tm.name)
			vm := &v.methods[j]
			vmName := V.nameOff(vm.name)
			if vmName.name() == tmName.name() && V.typeOff(vm.typ) == t.typeOff(tm.typ) {
				if !tmName.isExported() {
					tmPkgPath := tmName.pkgPath()
					if tmPkgPath == "" {
						tmPkgPath = t.pkgPath.name()
					}
					vmPkgPath := vmName.pkgPath()
					if vmPkgPath == "" {
						vmPkgPath = v.pkgPath.name()
					}
					if tmPkgPath != vmPkgPath {
						continue
					}
				}
				if i++; i >= len(t.methods) {
					return true
				}
			}
		}
		return false
	}

	v := V.uncommon()
	if v == nil {
		return false
	}
	i := 0
	vmethods := v.methods()
	for j := 0; j < int(v.mcount); j++ {
		tm := &t.methods[i]
		tmName := t.nameOff(tm.name)
		vm := vmethods[j]
		vmName := V.nameOff(vm.name)
		if vmName.name() == tmName.name() && V.typeOff(vm.mtyp) == t.typeOff(tm.typ) {
			if !tmName.isExported() {
				tmPkgPath := tmName.pkgPath()
				if tmPkgPath == "" {
					tmPkgPath = t.pkgPath.name()
				}
				vmPkgPath := vmName.pkgPath()
				if vmPkgPath == "" {
					vmPkgPath = V.nameOff(v.pkgPath).name()
				}
				if tmPkgPath != vmPkgPath {
					continue
				}
			}
			if i++; i >= len(t.methods) {
				return true
			}
		}
	}
	return false
}

// 直接可分配报告是否可以将V类型的值x直接分配给T类型的值。
// https:
// 忽略接口规则（在别处实现）
// 和理想常量规则（运行时没有理想常量）。
func directlyAssignable(T, V *rtype) bool {
	// x的V型与T型相同？
	if T == V {
		return true
	}

	// 否则T和V中至少有一个不能定义
	// 并且它们必须具有相同的类型。
	if T.hasName() && V.hasName() || T.Kind() != V.Kind() {
		return false
	}

	// x的类型T和V必须具有相同的基础类型。
	return haveIdenticalUnderlyingType(T, V, true)
}

func haveIdenticalType(T, V Type, cmpTags bool) bool {
	if cmpTags {
		return T == V
	}

	if T.Name() != V.Name() || T.Kind() != V.Kind() {
		return false
	}

	return haveIdenticalUnderlyingType(T.common(), V.common(), false)
}

func haveIdenticalUnderlyingType(T, V *rtype, cmpTags bool) bool {
	if T == V {
		return true
	}

	kind := T.Kind()
	if kind != V.Kind() {
		return false
	}

	// 同类的非复合类型具有相同的基础类型
	// （该类型的预定义实例）。
	if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
		return true
	}

	// 复合类型。
	switch kind {
	case Array:
		return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)

	case Chan:
		// 特例：
		// x为双向通道值，T为通道类型，
		// 且x的V型和T型元素类型相同。
		if V.chanDir() == bothDir && haveIdenticalType(T.Elem(), V.Elem(), cmpTags) {
			return true
		}

		// 否则继续测试相同的基础类型。
		return V.chanDir() == T.chanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)

	case Func:
		t := (*funcType)(unsafe.Pointer(T))
		v := (*funcType)(unsafe.Pointer(V))
		if t.outCount != v.outCount || t.inCount != v.inCount {
			return false
		}
		for i := 0; i < t.NumIn(); i++ {
			if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
				return false
			}
		}
		for i := 0; i < t.NumOut(); i++ {
			if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
				return false
			}
		}
		return true

	case Interface:
		t := (*interfaceType)(unsafe.Pointer(T))
		v := (*interfaceType)(unsafe.Pointer(V))
		if len(t.methods) == 0 && len(v.methods) == 0 {
			return true
		}
		// 可能有相同的方法，但仍然需要运行时转换。
		return false

	case Map:
		return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)

	case Ptr, Slice:
		return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)

	case Struct:
		t := (*structType)(unsafe.Pointer(T))
		v := (*structType)(unsafe.Pointer(V))
		if len(t.fields) != len(v.fields) {
			return false
		}
		if t.pkgPath.name() != v.pkgPath.name() {
			return false
		}
		for i := range t.fields {
			tf := &t.fields[i]
			vf := &v.fields[i]
			if tf.name.name() != vf.name.name() {
				return false
			}
			if !haveIdenticalType(tf.typ, vf.typ, cmpTags) {
				return false
			}
			if cmpTags && tf.name.tag() != vf.name.tag() {
				return false
			}
			if tf.offsetEmbed != vf.offsetEmbed {
				return false
			}
		}
		return true
	}

	return false
}

type structTypeUncommon struct {
	structType
	u uncommonType
}

// toType将*rtype转换为可以返回
// 到package reflect客户端的类型。在gc中，唯一的问题是必须用nil类型替换nil*rtype，但在gccgo中，此
// 函数负责确保同一
// 类型的多个*rtype合并为一个类型。
func toType(t *rtype) Type {
	if t == nil {
		return nil
	}
	return t
}

// ifaceIndir报告t是否间接存储在接口值中。
func ifaceIndir(t *rtype) bool {
	return t.kind&kindDirectIface == 0
}
